package com.jspgou.cms.action.front;

import static com.jspgou.cms.Constants.MEMBER_SYS;
import static com.jspgou.cms.Constants.STORE_SYS;

import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.jspgou.cms.entity.Order;
import com.jspgou.cms.entity.OrderItem;
import com.jspgou.cms.entity.OrderReturn;
import com.jspgou.cms.entity.Payment;
import com.jspgou.cms.entity.Product;
import com.jspgou.cms.entity.ProductFashion;
import com.jspgou.cms.entity.ShopMember;
import com.jspgou.cms.entity.ShopScore;
import com.jspgou.cms.manager.OrderMng;
import com.jspgou.cms.manager.OrderReturnMng;
import com.jspgou.cms.manager.PaymentMng;
import com.jspgou.cms.manager.ProductFashionMng;
import com.jspgou.cms.manager.ProductMng;
import com.jspgou.cms.manager.ShopMemberMng;
import com.jspgou.cms.manager.ShopScoreMng;
import com.jspgou.cms.web.CmsUtils;
import com.jspgou.cms.web.ShopFrontHelper;
import com.jspgou.cms.web.SiteUtils;
import com.jspgou.common.security.annotation.Secured;
import com.jspgou.common.web.springmvc.MessageResolver;
import com.jspgou.core.entity.ShopDictionary;
import com.jspgou.core.entity.Website;
import com.jspgou.core.manager.ShopDictionaryMng;
import com.jspgou.core.web.WebErrors;
import com.jspgou.core.web.front.FrontHelper;

@Secured
@Controller
public class OrderReturnAct {
	private static final Logger log = LoggerFactory.getLogger(OrderReturnAct.class);
	
	private static final String NODELIVERY_ORDER_RETURN = "tpl.noDeliveryOrderReturn";
	private static final String DELIVERYED_ORDER_RETURN = "tpl.DeliveryedOrderReturn";
	private static final String NODELIVERY_RETURN_MONEY_SUCCESS = "tpl.NoDeliveryedReturnMoneySuccess";
	private static final String DELIVERY_RETURN_MONEY_SUCCESS = "tpl.DeliveryedReturnMoneySuccess";
	/**
	 * 店铺订单退货详情页
	 */
	private static final String TPL_RETURN_ORDER_VIEW="tpl.returnOrderView";
	private static final String TPL_RETURN_SHIPPINGADDRESS="tpl.shippingAddress";
	
	// 订单退款申请页
	@RequestMapping(value = "/orderReturn/orderReturn.jspx")
	public String getOrderReturn(Long orderId,Boolean delivery,
			HttpServletRequest request,ModelMap model){
		Website web = SiteUtils.getWeb(request);
		ShopMember member=CmsUtils.getMember(request);
		if(member==null){
			return "redirect:../login.jspx";
		}
		WebErrors errors=validateOrderView(orderId,member,request);
		if(errors.hasErrors()){
			return FrontHelper.showError(errors, web, model, request);
		}
		String uploadRoot=web.getUploadUrl();
		model.addAttribute("uploadRoot", uploadRoot);
		Order order = orderMng.findById(orderId);
		ShopFrontHelper.setCommonData(request, model, web);
		List<ShopDictionary> ndList=null;
		//退款支付类型
		List<ShopDictionary> returnList=shopDictionaryMng.getList("refundTypes");
		model.addAttribute("returnList",returnList);
		model.addAttribute("order", order);	
		model.addAttribute("delivery", delivery);
		if(delivery){
			//已发货的退货原因list
			ndList=shopDictionaryMng.getList("returnReasonType");
			model.addAttribute("ndList", ndList);
			//已发货申请退款页
			return web.getTplSys(MEMBER_SYS, MessageResolver.getMessage(request, DELIVERYED_ORDER_RETURN), request);
		}else{
			//未发货退款原因list
			ndList=shopDictionaryMng.getList("refundReasonsType");
			model.addAttribute("ndList", ndList);
			//未发货申请退款页
			return web.getTplSys(MEMBER_SYS, MessageResolver.getMessage(request, NODELIVERY_ORDER_RETURN), request);
		}
	}
	
	// 订单退款申请提交页
	@RequestMapping(value = "/orderReturn/orderReturnRefer.jspx", method = RequestMethod.POST)
	public String getOrderReturnRefer(OrderReturn bean,String alipayId,Long orderId,Boolean delivery,
			String reasonId,String[] picPaths, String[] picDescs,HttpServletRequest request,ModelMap model){
		Website web = SiteUtils.getWeb(request);
		String uploadRoot=web.getUploadUrl();
		model.addAttribute("uploadRoot", uploadRoot);
		ShopMember member=CmsUtils.getMember(request);
		if(member==null){
			return "redirect:../login.jspx";
		}
		WebErrors errors = validateOrderView(orderId, member, request);
		if (errors.hasErrors()) {
			return FrontHelper.showError(errors, web, model, request);
		}
		Order order = orderMng.findById(orderId);
		//判断此退货订单是否存在
		if(manager.returnOrderExist(order)==false){
			ShopFrontHelper.setCommonData(request, model, web);
			errors.addError(productMng.getTipFile("create.orderReturn"));
		    return FrontHelper.showError(errors, web, model, request);
		}
		//生成退款记录
		OrderReturn orderReturn=manager.save(bean,order,alipayId,reasonId,delivery,picPaths,picDescs);
		log.debug("orderReturn createTime is: {}", orderReturn.getCreateTime());
		//修改订单
		order.setReturnOrder(orderReturn);
		//修改订单状态退款协议等待卖家确认中
		orderMng.updateByUpdater(order);
		model.addAttribute("order", order);	
		model.addAttribute("orderReturn", orderReturn);
		ShopFrontHelper.setCommonData(request, model, web);
		if(delivery){
			return web.getTplSys(MEMBER_SYS, MessageResolver.getMessage(request,
					   DELIVERY_RETURN_MONEY_SUCCESS), request);
		}else{
		     return web.getTplSys(MEMBER_SYS, MessageResolver.getMessage(request,
				   NODELIVERY_RETURN_MONEY_SUCCESS), request);
		}
	}
	
	//退货订单删除
	@RequestMapping(value="/orderReturn/delete.jspx")
	public String delete(Long[] returnId,HttpServletRequest request,ModelMap model,Integer pageNo){
		OrderReturn[] beans;
		try{
//			beans=manager.deleteByIds(returnId);
//			for(OrderReturn bean:beans){
//				log.info("delete Order id={}", bean.getId());
//			}
		}catch(Exception e){
		}
		model.addAttribute("pageNo", pageNo);
		return "redirect:orderSt/returnList.jspx";
	}
	
	//待审按钮
	@RequestMapping(value="/orderReturn/returnaffirm.jspx",method = RequestMethod.POST)
	public String returnaffirm(Long id, HttpServletRequest request, ModelMap model){
		Website web=SiteUtils.getWeb(request);
		ShopMember member=CmsUtils.getMember(request);
		if(member==null){
			return "redirect:../login.jspx";
		}
		String url=web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_SHIPPINGADDRESS), request);
		OrderReturn entity=manager.findById(id);
		//没有发货的情况下直接可以审核
		if(entity.getOrder().getShippingStatus()==1){
			//把状态从“待审”改为“已审”
			entity.setStatus(2);
			manager.update(entity);
			url=web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_ORDER_VIEW), request);
		}
		model.addAttribute("order", manager.findById(id).getOrder());
		model.addAttribute("orderReturn", entity);
		ShopFrontHelper.setCommonData(request, model, web);
		return url;
	}
	
	@RequestMapping(value="/orderReturn/o_shippingAddress.jspx",method = RequestMethod.POST)
	public String shippingAddress(Long id,String shippingAddress,String remind,HttpServletRequest request, ModelMap model){
		Website web=SiteUtils.getWeb(request);
		ShopMember member=CmsUtils.getMember(request);
		if(member==null){
			return "redirect:../login.jspx";
		}
		OrderReturn entity=manager.findById(id);
		//卖家必须填写给买家的收货地址，否则不提供审核机制
		if(StringUtils.isNotBlank(shippingAddress)){			
			entity.setShippingAddress(shippingAddress);
			//把状态从“待审”改为“已审”
			entity.setStatus(2);
		}
		entity.setRemind(remind);
		manager.update(entity);
		model.addAttribute("order", manager.findById(id).getOrder());
		model.addAttribute("orderReturn", entity);
		ShopFrontHelper.setCommonData(request, model, web);
		return web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_ORDER_VIEW), request);
	}
		
	//退回按钮
	@RequestMapping(value="/orderReturn/returnsendback.jspx",method = RequestMethod.POST)
	public String sendback(Long id,HttpServletRequest request,ModelMap model){
		Website web=SiteUtils.getWeb(request);
		ShopMember member=CmsUtils.getMember(request);
		if(member==null){
			return "redirect:../login.jspx";
		}
		OrderReturn entity=manager.findById(id);
		//把状态从“待审”改为“拒绝”
		entity.setStatus(3);
		manager.update(entity);
		model.addAttribute("order", manager.findById(id).getOrder());
		model.addAttribute("orderReturn", manager.findByOrderId(manager.findById(id).getOrder().getId()));
		ShopFrontHelper.setCommonData(request, model, web);
		return web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_ORDER_VIEW), request);
	}
		
		//收货按钮
		@RequestMapping(value="/orderReturn/returnsalesreturn.jspx",method = RequestMethod.POST)
		public String salesreturn(Long id,HttpServletRequest request,ModelMap model){
			Website web=SiteUtils.getWeb(request);
			ShopMember member=CmsUtils.getMember(request);
			if(member==null){
				return "redirect:../login.jspx";
			}
			OrderReturn entity=manager.findById(id);
			//把退款的订单状态改为“已收货”
			entity.setStatus(5);
			
			//处理库存     OrderItem表示订单项 ，ProductFashion表示款式集
			for(OrderItem item:entity.getOrder().getItems()){
				Product product=item.getProduct();
				if(item.getProductFash()!=null){
					ProductFashion fashion=item.getProductFash();
					//把商品款式集的库存相应的增加
					fashion.setStockCount(fashion.getStockCount()+item.getCount());
					//把商品的库存相应的增加
					product.setStockCount(product.getStockCount()+item.getCount());
					//把相应的销量减少
					product.setSaleCount(product.getSaleCount()-item.getCount());
					productFashionMng.update(fashion);
				}else{
					product.setSaleCount(product.getSaleCount()-item.getCount());
					product.setStockCount(product.getStockCount()+item.getCount());
				}
				productMng.update(product);
			}
			//会员冻结的积分
			member =entity.getOrder().getMember();
			//会员相应的积分减少
			member.setFreezeScore(member.getScore()-entity.getOrder().getScore());
			shopMemberMng.update(member);
			List<ShopScore> list =shopScoreMng.getlist(entity.getOrder().getCode());
			for(ShopScore s:list){
				//把积分表里相应的积分记录删除
				shopScoreMng.deleteById(s.getId());
			}
			manager.update(entity);
			model.addAttribute("order", manager.findById(id).getOrder());
			model.addAttribute("orderReturn", manager.findByOrderId(manager.findById(id).getOrder().getId()));
			ShopFrontHelper.setCommonData(request, model, web);
			return web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_ORDER_VIEW), request);
		}
		
		//退款按钮
		@RequestMapping(value="/orderReturn/returnreimburse.jspx",method = RequestMethod.POST)
		public String reimburse(Long id,HttpServletRequest request,HttpServletResponse response,ModelMap model){
			Website web=SiteUtils.getWeb(request);
			ShopMember member=CmsUtils.getMember(request);
			if(member==null){
				return "redirect:../login.jspx";
			}
			OrderReturn entity = manager.findById(id);
			Payment pay = paymentMng.findByCode("alipay");
			//如果pay!=null表示用支付宝账户汇款
			if(pay!=null){	
		    	PrintWriter out = null;
				try {
					//退款过程经过支付宝操作
					String aliURL = alipayReturn(pay,web,entity, request, model);
					response.setContentType("text/html;charset=UTF-8");
					out = response.getWriter();
					out.print(aliURL);
				} catch (Exception e) {
				}finally{
					out.close();
				}
	    	}
			//这种表示不是用支付宝账户，可能是用本地账户，数据库当中还没有添加
//			else{
//	    		ShopMember shopMember = entity.getOrder().getMember();
//	    		shopMember.setMoney(shopMember.getFreezeScore()+entity.getMoney());
//	    		shopMemberMng.update(shopMember);
//	    	}
			//把退款订单状态改为“已退款”状态
			entity.setStatus(6);
			manager.update(entity);
			model.addAttribute("order", manager.findById(id).getOrder());
			model.addAttribute("orderReturn", manager.findByOrderId(manager.findById(id).getOrder().getId()));
			ShopFrontHelper.setCommonData(request, model, web);
			return web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_ORDER_VIEW), request);		
		}
		
		//完成按钮
		@RequestMapping(value="/orderReturn/returnaccomplish.jspx",method = RequestMethod.POST)
		public String accomplish(Long id, HttpServletRequest request,ModelMap model) throws ParseException{
			Website web=SiteUtils.getWeb(request);
			ShopMember member=CmsUtils.getMember(request);
			if(member==null){
				return "redirect:../login.jspx";
			}
			OrderReturn entity =manager.findById(id);
			//把退款的订单状态改为“完成”
			entity.setStatus(7);
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
			String time=df.format(new Date());
			Date test = df.parse(time);
			entity.setFinishedTime(test);
			Order order=manager.findById(id).getOrder();
			//把订单的状态改为了“已取消”
			order.setStatus(3);
			manager.update(entity);
			orderMng.updateByUpdater(order);
			model.addAttribute("order", manager.findById(id).getOrder());
			model.addAttribute("orderReturn", manager.findByOrderId(manager.findById(id).getOrder().getId()));
			ShopFrontHelper.setCommonData(request, model, web);
			return web.getTplSys(STORE_SYS, MessageResolver.getMessage(request,TPL_RETURN_ORDER_VIEW), request);
		}
		
		private String alipayReturn(Payment pay,Website web,OrderReturn orderReturn,
				HttpServletRequest request,ModelMap model){
			////////////////////////////////////请求参数//////////////////////////////////////
			//必填参数//
			Date date=new Date();
			SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
			SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String date1=sdf.format(date);
			//退款批次号。格式为：退款日期（8位当天日期）+流水号（3～24位，不能接受“000”，但是可以接受英文字符）
//			String batch_no = request.getParameter("batch_no");
			String batch_no = date1.concat(String.valueOf(orderReturn.getId()*100));
			//退款请求时间
//			String refund_date = request.getParameter("refund_date");
			String refund_date = sdf1.format(date);
			//退款总笔数
//			String batch_num = request.getParameter("batch_num");
			String batch_num =String.valueOf(1);
			//单笔数据集
//			String detail_data =  new String(request.getParameter("detail_data").getBytes("ISO-8859-1"),"gbk");
			String detail_data = orderReturn.getOrder().getId().toString()+"^"+1.00+"^"+orderReturn.getShopDictionary().getName();
			//格式：第一笔交易#第二笔交易#第三笔交易
		        //第N笔交易格式：交易退款信息
		        //交易退款信息格式：原付款支付宝交易号^退款总金额^退款理由
		        //注意：
		        //1.detail_data中的退款笔数总和要等于参数batch_num的值
		        //2.detail_data的值中不能有“^”、“|”、“#”、“$”等影响detail_data的格式的特殊字符
		        //3.detail_data中退款总金额不能大于交易总金额
		        //4.一笔交易可以多次退款，只需要遵守多次退款的总金额不超过该笔交易付款时金额。
		        //5.不支持退分润功能
			//选填参数（以下两个参数不能同时为空）
			//卖家支付宝账号
//			String seller_email = request.getParameter("seller_email");
			String seller_email = pay.getSellerEmail();
			//卖家用户ID
//			String seller_user_id = request.getParameter("seller_user_id");
		    String seller_user_id = pay.getSellerKey();
			//服务器页面跳转同步通知页面
			String notify_url="http://"+web.getDomain()+"/cart/aliReturn.jspx";
			//////////////////////////////////////////////////////////////////////////////////
			//把请求参数打包成数组
			Map<String, String> sParaTemp = new HashMap<String, String>();
		 	sParaTemp.put("partner", pay.getPartner());
			sParaTemp.put("seller_email", seller_email);
			sParaTemp.put("seller_user_id", seller_user_id);
			
			
	        sParaTemp.put("batch_no", batch_no);
	        sParaTemp.put("refund_date", refund_date);
	        sParaTemp.put("batch_num", batch_num);
	        sParaTemp.put("detail_data", detail_data);
	        sParaTemp.put("notify_url", notify_url);
			//构造函数，生成请求URL  
			String sHtmlText=null;
			try {
				sHtmlText = refund_fastpay_by_platform_pwd(sParaTemp);
			} catch (Exception e) {
				e.printStackTrace();
			}
	        //out.println(sHtmlText);
			return sHtmlText;
		}
		
		/**
	     * 支付宝提供给商户的服务接入网关URL(新)
	     */
	    private static final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
		
		/**
	     * 构造即时到账批量退款有密接口
	     * @param sParaTemp 请求参数集合
	     * @return 支付宝返回表单提交HTML信息
	     * @throws Exception 
	     */
	    public static String refund_fastpay_by_platform_pwd(Map<String, String> sParaTemp) throws Exception {
	    	//增加基本配置
	        sParaTemp.put("service", "refund_fastpay_by_platform_pwd");
	        sParaTemp.put("_input_charset", "UTF-8");
	        String strButtonName="退款";
	        return buildForm(sParaTemp, ALIPAY_GATEWAY_NEW,"get",strButtonName);
	    }
	    
	    /**
	     * 构造提交表单HTML数据
	     * @param sParaTemp 请求参数数组
	     * @param gateway 网关地址
	     * @param strMethod 提交方式。两个值可选：post、get
	     * @param strButtonName 确认按钮显示文字
	     * @return 提交表单HTML文本
	     */
	    public static String buildForm(Map<String, String> sParaTemp, String gateway, String strMethod,
	                                   String strButtonName) {
	        //待请求参数数组
	        Map<String, String> sPara = buildRequestPara(sParaTemp);
	        List<String> keys = new ArrayList<String>(sPara.keySet());

	        StringBuffer sbHtml = new StringBuffer();

	        sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + gateway
	                      + "_input_charset=" + "UTF-8" + "\" method=\"" + strMethod
	                      + "\">");

	        for (int i = 0; i < keys.size(); i++) {
	            String name = (String) keys.get(i);
	            String value = (String) sPara.get(name);

	            sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>");
	        }

	        //submit按钮控件请不要含有name属性
	        sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>");
	        sbHtml.append("<script>document.forms['alipaysubmit'].submit();</script>");

	        return sbHtml.toString();
	    }
	    
	    /**
		    * 生成要请求给支付宝的参数数组
		    * @param sParaTemp 请求前的参数数组
		    * @return 要请求的参数数组
		    */
		   private static Map<String, String> buildRequestPara(Map<String, String> sParaTemp) {
		       //除去数组中的空值和签名参数
		       Map<String, String> sPara = paraFilter(sParaTemp);
		       //生成签名结果
		       String mysign = buildMysign(sPara);

		       //签名结果与签名方式加入请求提交参数组中
		       sPara.put("sign", mysign);
		       sPara.put("sign_type", "MD5");

		       return sPara;
		   }
		   
		   public static String buildMysign(Map<String, String> sArray) {
		       String prestr = createLinkString(sArray); //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
		       prestr = prestr +sArray.get("key"); //把拼接后的字符串再与安全校验码直接连接起来
		       String mysign = md5(prestr);
		       return mysign;
		   }
		   
		   public static String md5(String text) {

		       return DigestUtils.md5Hex(getContentBytes(text, "UTF-8"));

		   }
		   
		   private static byte[] getContentBytes(String content, String charset) {
		       if (charset == null || "".equals(charset)) {
		           return content.getBytes();
		       }

		       try {
		           return content.getBytes(charset);
		       } catch (UnsupportedEncodingException e) {
		           throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
		       }
		   }
		   
		   /** 
		    * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
		    * @param params 需要排序并参与字符拼接的参数组
		    * @return 拼接后字符串
		    */
		   public static String createLinkString(Map<String, String> params) {

		       List<String> keys = new ArrayList<String>(params.keySet());
		       Collections.sort(keys);

		       String prestr = "";

		       for (int i = 0; i < keys.size(); i++) {
		           String key = keys.get(i);
		           String value = params.get(key);

		           if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
		               prestr = prestr + key + "=" + value;
		           } else {
		               prestr = prestr + key + "=" + value + "&";
		           }
		       }

		       return prestr;
		   }
		   
		   /** 
		    * 除去数组中的空值和签名参数
		    * @param sArray 签名参数组
		    * @return 去掉空值与签名参数后的新签名参数组
		    */
		   public static Map<String, String> paraFilter(Map<String, String> sArray) {

		       Map<String, String> result = new HashMap<String, String>();

		       if (sArray == null || sArray.size() <= 0) {
		           return result;
		       }

		       for (String key : sArray.keySet()) {
		           String value = sArray.get(key);
		           if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
		               || key.equalsIgnoreCase("sign_type")) {
		               continue;
		           }
		           result.put(key, value);
		       }

		       return result;
		   }
	
	private WebErrors validateOrderView(Long orderId,ShopMember member,
			HttpServletRequest request){
		WebErrors errors=WebErrors.create(request);
		if(errors.ifNull(orderId, "orderId")){
			return errors;
		}
		Order order=orderMng.findById(orderId);
		if(errors.ifNotExist(order, Order.class, orderId)){
			return errors;
		}
		//判断订单用户id和用户id是否是同一个人
		if(!order.getMember().getId().equals(member.getId())){
			errors.noPermission(Order.class, orderId);
			return errors;
		}
		return errors;
	}
	
	public static void main(String []args) throws ParseException{
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
		String time=df.format(new Date());
		Date test = df.parse(time);
	}
	
	@Autowired
	private OrderMng orderMng;
	@Autowired
	private OrderReturnMng manager;
	@Autowired
	private ShopDictionaryMng shopDictionaryMng;
	@Autowired
	private ProductMng productMng;
	@Autowired
	private PaymentMng paymentMng;
	@Autowired
	private ShopScoreMng shopScoreMng;
	@Autowired
	private ProductFashionMng productFashionMng;
	@Autowired
	private ShopMemberMng shopMemberMng;
}
